
#import "GameManager.h"

int W=320;
int H=480;

@implementation GameManager

#pragma mark ============================= Init Methods ===============================

+ (GameManager*) getInstance  {
    
    static GameManager* gameManager;
		
	if (!gameManager) {
        gameManager = [[GameManager alloc] init];
		[gameManager preloader];            
	}
	    
    return gameManager;
}

- (void) preloader {
    sprites = [[NSMutableArray alloc] initWithCapacity:20];
    newSprites = [[NSMutableArray alloc] initWithCapacity:20];
    destroyableSprites = [[NSMutableArray alloc] initWithCapacity:20];
   
    sequencer = [[NSMutableArray alloc] initWithCapacity:99];
    
    //pre-Load sounds
    [[SoundOAL getInstance] loadSound: @"sound1.wav" Hz: 44100];
    [[SoundOAL getInstance] loadSound: @"sound2.wav" Hz: 44100];
    [[SoundOAL getInstance] loadSound: @"sound3.wav" Hz: 44100];
    [[SoundOAL getInstance] loadSound: @"sound4.wav" Hz: 44100];
    [[SoundOAL getInstance] loadSound: @"sound5.wav" Hz: 44100];
    [[SoundOAL getInstance] loadSound: @"track1.wav" Hz: 44100];
    
    background = [self getPic: @"background.png"];    
    state = LOAD_GAME;
}

- (void) loadGame { 
    [sprites removeAllObjects];
    [newSprites removeAllObjects];
    [destroyableSprites removeAllObjects];      
}

- (void) createSprite: (int) type 
                speed: (CGPoint) sxy 
                  pos: (CGPoint) pxy {    
    if (type == CIRCLE) {        
        Circle *circle = [[Circle alloc] initWithRadius: 10 
                                                    pos: pxy
                          ];        
        [circle setType: CIRCLE];
        [newSprites addObject: circle];
        [circle release];       
    } else {
        NSLog(@"ERROR: Unknown sprite type: %i", type);
    }    
}

#pragma mark ============================= Game Handler ===============================

- (void) touchBegan: (CGPoint) p {    
    [self handleStates];       
    
    if (p.x < 130 && p.y > H-50) {        
        static bool playMusic = true;
        if (playMusic) {
            [[SoundOAL getInstance] stopSound: @"track1.wav"];
            playMusic = false;
            NSLog(@"Loop off");
        } else {
            [[SoundOAL getInstance] loopSound: @"track1.wav"];
            playMusic = true;
            NSLog(@"Loop on");
        }           
    } else if (p.x > W-60 && p.y > H-50) {
        NSLog(@"Clear sequencer");
        [sequencer removeAllObjects];
    } else {
        [self createSprite: CIRCLE 
                     speed: CGPointMake(0, 0) 
                       pos: p];
        
        SoundEvent *event = [[SoundEvent alloc] initWithTime: time pos: p];
        [sequencer addObject: event];
        [event release];
    }   
}

- (void) touchMoved: (CGPoint) p {}
- (void) touchEnded {}

- (void) handleStates {   
    if (state == START_GAME) {
        state = PLAY_GAME;
    }
}

- (void) drawStatesWithFrame: (CGRect) frame { 
    W = frame.size.width;
    H = frame.size.height;     
    switch (state) {
        case LOAD_GAME: 
            [self loadGame];
            state = START_GAME;
            [[SoundOAL getInstance] loopSound: @"track1.wav"];           
            break;
        case START_GAME:
            [background drawAtPoint: CGPointMake(0, 0)];           
            [self drawString: @"Tap screen to start!" at: CGPointMake(5, 5)];
            break;    
        case PLAY_GAME:
            [self playGame];
            break;          
        default: NSLog(@"ERROR: Unknown state: %i", state);
            break;
    }    
}	 

- (void) playGame {   
    [background drawAtPoint: CGPointMake(0, 0)];
    [self manageSprites];             
    [self renderSprites];
    
    [self drawString: @"Loop on/off" at: CGPointMake(5, H-30)];
    [self drawString: @"Clear" at: CGPointMake(W-60, H-30)];
    
    time ++;
    if (time > 100) { 
        time = 0;
    } 
    
    for (SoundEvent *event in sequencer) {
        //NSLog(@"Events: %i eventTime: %i time: %i ", [sequencer count], [event getTime], time);
        if ([event getTime] == time) {
            [self createSprite: CIRCLE 
                         speed: CGPointMake(0, 0) 
                           pos: [event getPos]];
        }
    }  
} 

- (void) checkSprite: (Sprite *) sprite {}

#pragma mark ============================= Helper Methods ===============================

- (void) setState: (int) stt {
    state = stt;
}

- (void) manageSprites {
    //NSLog(@"Sprites: %i destroyable: %i new: %i", [sprites count], [destroyableSprites count], [newSprites count]);
    
    for (Sprite *destroyableSprite in destroyableSprites) { 
        for (Sprite *sprite in sprites) { 
            if (destroyableSprite == sprite) { 
                [sprites removeObject: sprite];
                break;
            }
        }   
    }  

    for (Sprite *newSprite in newSprites){ 
        [sprites addObject: newSprite];   
    } 
    
    [destroyableSprites removeAllObjects]; 
    [newSprites removeAllObjects];
}

- (void) renderSprites {
    for (Sprite *sprite in sprites) { 
        if ([sprite isActive]) {             
            [self checkSprite: sprite];
            [sprite draw]; 
        } else {
            [destroyableSprites addObject: sprite]; 
        }    
    } 
}

- (NSMutableDictionary *) getDictionary {
	if (!dictionary) { 
		dictionary = [[NSMutableDictionary alloc] init]; 
	}
	return dictionary;
}

- (UIImage *) getPic: (NSString*) picName {
	@try { 
		UIImage *pic = [[self getDictionary] objectForKey: picName];
		if (!pic) {
			pic = [UIImage imageNamed: picName]; 
			[[self getDictionary] setObject: pic forKey: picName];
            int memory = pic.size.width*pic.size.height*4;
			NSLog(@"%@ stored, Size: %i KB", picName, memory/1024);
            [pic release]; 
		}          
		return pic;
	} 
	@catch (id theException) {
		NSLog(@"ERROR: %@ not found!", picName);		
	} 
	return nil;
}

- (int) getRndBetween: (int) bottom and: (int) top {		
	int rnd = bottom + (arc4random() % (top+1-bottom)); 
	return rnd;
} 

- (void) drawString: (NSString *) str at: (CGPoint) p {
    UIFont *uif = [UIFont fontWithName: @"Verdana-Italic" size: 20];
	CGContextSetRGBFillColor(UIGraphicsGetCurrentContext(), 0, 0, 0, 1);
    [str drawAtPoint: p withFont: uif]; 
} 

- (void) dealloc {        
    [sprites release];
    [newSprites release];
    [destroyableSprites release];
    [sequencer release];
    [dictionary release];
    [super dealloc];
}

@end
